home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / other / diskreader / adfreader.asm next >
Assembly Source File  |  2000-02-28  |  8KB  |  431 lines

  1. ; adfreader.asm - essential functionality for game disk installers.
  2. ; Supports Amiga Disk Files instead of trackdisk
  3. ; © 1998-1999 Kyzer/CSG
  4.  
  5.     IFND    FILEMODE
  6. FILEMODE=0
  7.     ENDC
  8.     IFND    MESSAGES
  9. MESSAGES=0
  10.     ENDC
  11.  
  12.     IFD    NO_INCLUDES
  13. MODE_OLDFILE=1005        ; from dos/dos.i
  14. MODE_NEWFILE=1006
  15. OFFSET_BEGINNING=-1
  16. ERROR_NOT_A_DOS_DISK=225
  17. _LVOOpen=-30            ; from dos/dos_lib.i
  18. _LVOClose=-36
  19. _LVORead=-42
  20. _LVOWrite=-48
  21. _LVOSeek=-66
  22. _LVOIoErr=-132
  23. _LVOSetIoErr=-462
  24. _LVOPrintFault=-474
  25. _LVOReadArgs=-798
  26. _LVOFreeArgs=-858
  27. _LVOPutStr=-948
  28. _LVOVPrintf=-954
  29. _LVOCloseLibrary=-414        ; from exec/exec_lib.i
  30. _LVODoIO=-456
  31. _LVOOpenLibrary=-552
  32.     ELSE
  33.     include    dos/dos.i
  34.     include    dos/dos_lib.i
  35.     include    exec/exec_lib.i
  36.     ENDC
  37.  
  38. DOSTRACKLEN=512*11
  39.  
  40. BUFFER    MACRO    ; buffername
  41. \1    equ    __trk
  42.     ENDM
  43.  
  44. FAILURE    MACRO    ; [reason]
  45.     IFEQ    NARG
  46.     suba.l    a0,a0
  47.     ELSE
  48.     lea    \1,a0
  49.     ENDC
  50.     bra    __fail
  51.     ENDM
  52.  
  53. RAWREAD    MACRO    ; track
  54.     lea    __trk,a0
  55.     move.l    \1,d0
  56.     bsr    __rawrd
  57.     ENDM
  58. RESYNC    MACRO    ; wordsync
  59.     lea    __trk,a0
  60.     move.l    \1,d0
  61.     bsr    __sync
  62.     ENDM
  63. DOSREAD    MACRO    ; track
  64.     lea    __trk,a0
  65.     move.l    \1,d0
  66.     bsr    __dosrd
  67.     ENDM
  68.  
  69.     IFEQ    FILEMODE
  70. WRITE    MACRO    ; length, [offset]
  71.     IFEQ    NARG-2
  72.     lea    __trk,a0
  73.     add.l    \2,a0
  74.     ELSE
  75.     lea    __trk,a0
  76.     ENDC
  77.     move.l    \1,d0
  78.     bsr    __write
  79.     ENDM
  80.  
  81. WRITEDOS MACRO    ; track
  82.     DOSREAD    \1
  83.     WRITE    #DOSTRACKLEN
  84.     ENDM
  85.  
  86.     ELSE
  87. SAVEF    MACRO    ; filename, buffer, length
  88.     lea    \1,a0
  89.     lea    \2,a1
  90.     move.l    \3,d0
  91.     bsr    __savef
  92.     ENDM
  93.     ENDC
  94.  
  95. ;------------------------------------
  96.  
  97. call    macro
  98.     jsr    _LVO\1(a6)
  99.     endm
  100.  
  101. initstk    macro    ; stack_symbol, stackreg
  102.     link    \2,#\1
  103.     move.l    sp,a0
  104. .clr\@    clr.w    (a0)+
  105.     cmp.l    a0,\2
  106.     bne.s    .clr\@
  107.     endm
  108.  
  109. stackf    MACRO    ; stack_symbol, stackelement_symbol, [size=4]
  110.     IFND    \1
  111. \1    set    0
  112.     ENDC
  113.     IFGE    NARG-3
  114. \1    set    \1-(\3)
  115.     ELSE
  116. \1    set    \1-4
  117.     ENDC
  118. \2    equ    \1
  119.     ENDM
  120.  
  121.     IFNE    FILEMODE
  122.     stackf    stk, __adfname
  123. __args=__adfname
  124. __nargs=1
  125. __tmpl    macro
  126.     dc.b    'ADF/A',0
  127.     endm
  128.     ELSE
  129.     stackf    stk, __output
  130.     stackf    stk, __adfname
  131. __args=__adfname
  132. __nargs=2
  133. __tmpl    macro
  134.     dc.b    'ADF/A,OUTPUT/A',0
  135.     endm
  136.     ENDC
  137.  
  138.     stackf    stk, __rdargs    ; returned by ReadArgs()
  139.     stackf    stk, __adffh    ; input filehandle
  140.     stackf    stk, __outfh    ; output filehandle (NULL in filemode)
  141.     stackf    stk, __initsp    ; initial (sp): move to sp then rts to quit
  142.     stackf    stk, __reason    ; ptr to textual reason for failure, or NULL
  143.     stackf    stk, execbase    ; exec.library
  144.     stackf    stk, dosbase    ; dos.library
  145.  
  146.     stackf    stk, __sltab, 160*4    ; sync and length table
  147.     stackf    stk, __otab,  160*4    ; offset table
  148.  
  149.  
  150.     section    diskreader,code
  151.     link    a5,#stk
  152.     move.l    4.w,a6
  153.     move.l    a6,execbase(a5)
  154.  
  155.     suba.l    a1,a1
  156.     jsr    -$126(a6)
  157.     move.l    d0,a0
  158.     lea    $94(a0),a0
  159.  
  160.     clr.l    __reason(a5)
  161.     moveq    #100,d7
  162.  
  163.     moveq    #37,d0
  164.     lea    __dosnm(pc),a1
  165.     call    OpenLibrary
  166.     move.l    d0,dosbase(a5)
  167.     beq    .nodos
  168.     move.l    d0,a6
  169.  
  170.     lea    __templ(pc),a0
  171.     move.l    a0,d1
  172.     lea    __args(a5),a0
  173.     move.l    a0,d2
  174.     REPT    __nargs
  175.     clr.l    (a0)+
  176.     ENDR
  177.     moveq    #0,d3
  178.     call    ReadArgs
  179.     move.l    d0,__rdargs(a5)
  180.     beq    .noargs
  181.  
  182.     IFEQ    FILEMODE
  183.     move.l    __output(a5),d1
  184.     move.l    #MODE_NEWFILE,d2
  185.     call    Open
  186.     move.l    d0,__outfh(a5)
  187.     beq    .nofile
  188.     ENDC
  189.  
  190.     ; open ADF file
  191.     move.l    __adfname(a5),d1
  192.     move.l    #MODE_OLDFILE,d2
  193.     call    Open
  194.     move.l    d0,__adffh(a5)
  195.     beq    .noadf
  196.  
  197.     move.l    d0,d4
  198.     lea    __sltab(a5),a2
  199.  
  200.     ; check ADF header
  201.  
  202.     move.l    d4,d1
  203.     move.l    a2,d2
  204.     moveq    #8,d3
  205.     call    Read
  206.     tst.l    d0
  207.     bmi.s    .notadf
  208.     cmp.l    #"UAE-",(a2)
  209.     bne.s    .notext
  210.     cmp.l    #"-ADF",4(a2)
  211.     bne.s    .notext
  212.  
  213.     ; read sync/len table
  214.     move.l    d4,d1
  215.     move.l    a2,d2
  216.     move.l    #160*4,d3
  217.     call    Read
  218.     tst.l    d0
  219.     bmi.s    .notadf
  220.  
  221.     ; fill offsets table
  222.     lea    (8+160*4).w,a0    ; track 0 data immediately follows table/header
  223.     lea    __otab(a5),a1
  224.     move.w    #160-1,d0
  225.     moveq    #0,d1
  226. .loop    move.l    a0,(a1)+    ; put offset
  227.     move.l    (a2)+,d1
  228.     adda.w    d1,a0        ; add length of track to offset
  229.     dbra    d0,.loop
  230.     bra.s    .begin
  231.  
  232. .notext    lea    DOSTRACKLEN.w,a3    ; also support DOS-only ADFs
  233.     lea    __otab(a5),a1
  234.     move.w    #160-1,d0
  235. .loop2    move.l    a3,(a2)+    ; sync=$0000, length=DOSTRACKLEN
  236.     move.l    a0,(a1)+    ; put offset
  237.     add.l    a3,a0
  238.     dbra    d0,.loop2
  239.  
  240. .begin    bsr    __main
  241.  
  242.     move.l    dosbase(a5),a6
  243.  
  244.     IFNE    MESSAGES
  245.     pea    10<<24
  246.     move.l    sp,d1
  247.     call    PutStr    ; print a newline
  248.     addq.l    #4,sp
  249.     ENDC
  250.  
  251. .notadf    move.l    __adffh(a5),d1
  252.     call    Close
  253. .noadf
  254.     IFEQ    FILEMODE
  255.     move.l    __outfh(a5),d1
  256.     call    Close
  257. .nofile
  258.     ENDC
  259.     move.l    __rdargs(a5),d1
  260.     call    FreeArgs
  261. .noargs    moveq    #0,d7         ; returncode = 0
  262.     call    IoErr
  263.     move.l    d0,d1
  264.     beq.s    .nofail
  265.     bpl.s    .real        ; sometimes Read() sets error to -1
  266.     moveq    #0,d1
  267.     bra.s    .nofail
  268. .real    moveq    #20,d7        ; returncode = 20
  269. .nofail    move.l    __reason(a5),d2
  270.     call    PrintFault
  271.  
  272.     move.l    a6,a1
  273.     move.l    execbase(a5),a6
  274.     call    CloseLibrary
  275. .nodos    move.l    d7,d0
  276.     unlk    a5
  277.     rts
  278.  
  279.     IFNE    MESSAGES
  280. __prtrk    movem.l    d0-d2/a0,-(sp)
  281.     lea    __msg(pc),a0
  282.     move.l    a0,d1
  283.     move.l    sp,d2    ; points at D0 on the stack
  284.     move.l    dosbase(a5),a6
  285.     call    VPrintf
  286.     movem.l    (sp)+,d0-d2/a0
  287.     rts
  288.     ENDC
  289.  
  290. ;------------------------------------
  291. ; a0 = buffer, d0 = track
  292. __dosrd    movem.l    d2/d3/a2/a3/a6,-(sp)
  293.     IFNE    MESSAGES
  294.     bsr.s    __prtrk
  295.     ENDC
  296.     add.l    d0,d0
  297.     add.l    d0,d0
  298.     lea    __sltab(a5),a2
  299.     lea    __otab(a5),a3
  300.  
  301.     tst.w    (a2,d0.w)
  302.     beq.s    __rdcom    ; continue if DOS track
  303. __rdfai    lea    errtrk(pc),a0
  304.     bra.s    __fail
  305.     
  306. ;------------------------------------
  307. ; a0 = buffer, d0 = track
  308. __rawrd    movem.l    d2/d3/a2/a3/a6,-(sp)
  309.     IFNE    MESSAGES
  310.     bsr.s    __prtrk
  311.     ENDC
  312.     add.l    d0,d0
  313.     add.l    d0,d0
  314.     lea    __sltab(a5),a2
  315.     lea    __otab(a5),a3
  316.  
  317.     move.w    (a2,d0.w),(a0)+
  318.     beq.s    __rdfai        ; fail if DOS track
  319.  
  320. __rdcom    move.w    d0,-(sp)
  321.     move.l    __adffh(a5),d1
  322.     move.l    (a3,d0.w),d2        ; get offset in disk file
  323.     moveq    #OFFSET_BEGINNING,d3
  324.     move.l    dosbase(a5),a6
  325.     move.l    a0,-(sp)
  326.     call    Seek
  327.     move.l    __adffh(a5),d1
  328.     move.l    (sp)+,d2
  329.     moveq    #0,d3
  330.     move.w    (sp)+,d3
  331.     move.w    2(a2,d3.w),d3
  332.     call    Read
  333.     tst.l    d0
  334.     bmi.s    __rdfai
  335.     movem.l    (sp)+,d2/d3/a2/a3/a6
  336.     rts
  337.  
  338. ;------------------------------------
  339. ; a0 = failure reason
  340. __fail    move.l    a0,d0
  341.     beq.s    .noreas
  342.     move.l    d0,__reason(a5)
  343.     move.l    dosbase(a5),a6
  344.     move.l    #ERROR_NOT_A_DOS_DISK,d1
  345.     call    SetIoErr
  346. .noreas    move.l    __initsp(a5),sp
  347.     rts
  348.  
  349.     IFNE    FILEMODE
  350. ;------------------------------------
  351. ; a0 = filename, a1 = buffer, d0 = length
  352. __savef    movem.l    d2-d4/a6,-(sp)
  353.     move.l    a0,d1
  354.     move.l    a1,d3    ; d3 = buffer
  355.     move.l    d0,d4    ; d4 = length
  356.     move.l    #MODE_NEWFILE,d2
  357.     move.l    dosbase(a5),a6
  358.     call    Open
  359.     move.l    d0,d1    ; d1 = filehandle
  360.     move.l    d3,d2    ; d2 = buffer
  361.     move.l    d4,d3    ; d3 = length
  362.     move.l    d0,d4    ; d4 = filehandle
  363.     beq.s    __fail
  364.     call    Write
  365.     move.l    d0,d3
  366.     move.l    d4,d1
  367.     call    Close
  368.     tst.l    d3
  369.     bmi.s    __fail
  370.     movem.l    (sp)+,d2-d4/a6
  371.     rts
  372.  
  373.     ELSE
  374. ;------------------------------------
  375. ; a0 = buffer, d0 = length
  376. __write    movem.l    d2-d3/a6,-(sp)
  377.     move.l    a0,d2
  378.     move.l    d0,d3
  379.     move.l    __outfh(a5),d1
  380.     move.l    dosbase(a5),a6
  381.     call    Write
  382.     tst.l    d0
  383.     bmi.s    __fail
  384.     movem.l    (sp)+,d2-d3/a6
  385.     rts
  386.     ENDC
  387.  
  388. ;------------------------------------
  389. ; a0 = buffer d0 = sync
  390.  
  391. __sync    movem.l    d2-d3,-(sp)
  392.     move.l    a0,a1
  393.     subq    #2,a0
  394.     beq.s    .done
  395.     move.w    #($7ffe/2)-1,d2        ; search entire trackbuffer
  396. .nxtwrd    moveq    #16-1,d3        ; find a BIT distance... (0-15)
  397. .nxtbit    move.l    (a0),d1            ; and a BYTE distance.. (0-$7ffe)
  398.     lsr.l    d3,d1
  399.     cmp.w    d0,d1            ; ... for which we find the SYNCWORD
  400.     beq.s    .synced
  401.     dbra    d3,.nxtbit
  402.     addq.l    #2,a0
  403.     dbra    d2,.nxtwrd
  404.     lea    .err(pc),a0        ; searched through all 32k...
  405.     bra.s    __fail            ; ...no sync marker found
  406.  
  407. .synced    move.l    (a0),d1            ; match; now we shift all the remaining
  408.     addq.l    #2,a0            ; trackdata backwards by this BIT and
  409.     lsr.l    d3,d1            ; BYTE distance, so the first word in
  410.     move.w    d1,(a1)+        ; the trackbuffer is the SYNCWORD
  411.     dbra    d2,.synced
  412.     movem.l    (sp)+,d2-d3
  413. .done    rts
  414. .err    dc.b    "can't find sync mark",0
  415. errtrk    dc.b    "can't read track",0
  416. __dosnm    dc.b    "dos.library",0
  417. __templ    __tmpl
  418.     IFNE    MESSAGES
  419. __msg    dc.b    "reading track %ld",13,0
  420.     ENDC
  421.  
  422.     cnop    0,4
  423.  
  424.     ; create 32kb CHIP BSS hunk for trackbuffer
  425.     section    trackbuf,bss,chip
  426. __trk    ds.b    $7ffe
  427.  
  428.     ; return to main code section
  429.     section    diskreader,code
  430. __main    move.l    sp,__initsp(a5)
  431.